// 写一个自执行函数
(function (window) {

    const util={

    }

    util.random = function (min,max) {
        return Math.floor(Math.random()*(max-min+1)+min);
    }

    function Cube(size,options) {

        //  size不能为空
        if(!size){
            throw new Error("No size provided");
        }

        options = options || {};
        this.$model=null;
        this.$size=size;
        this.$xIndex=options.xIndex||0;
        this.$yIndex=options.yIndex||0;
        let cube = document.createElement('div');
        cube.style.width = this.$size + 'px';
        cube.style.height = this.$size + 'px';
        cube.style.position = 'absolute';
        cube.style.backgroundColor = 'lightseagreen';
        cube.style.borderCollapse = 'collapse';
        // 设置border
        cube.style.border = '1px solid black';
        options.className && cube.classList.add(options.className);
        this.$el = cube;
    }


    /**
     *
     * @param xIndex 代表方块在模型中的x轴位置
     * @param yIndex 代表方块在模型中y轴位置
     */

    Cube.prototype.moveTo=function (xIndex,yIndex) {
        this.$xIndex=xIndex;
        this.$yIndex=yIndex;
        this.draw()
    }

    Cube.prototype.rotate = function () {
        let temp=this.$xIndex;
        this.$xIndex=this.$yIndex;
        this.$yIndex=3-temp;
        this.draw();
    }


    Cube.prototype.draw = function(){
        this.$el.style.left = (this.$model.$xIndex+this.$xIndex)*this.$size + 'px';
        this.$el.style.top = (this.$model.$yIndex+this.$yIndex)*this.$size + 'px';
    }

    class Model{

        static DIRECTION = {
            DOWN: 1,
            UP: 2,
            LEFT: 3,
            RIGHT: 4
        }


        static DEFAULT_ROW_COUNT = 4;
        static DEFAULT_COL_COUNT = 4;
        /**
         * 构造函数
         * @param cubes 方块集合
         * @param direction 方向 1 向下 2 向上 3 向左 4 向右
         */
        constructor(container,cubes,direction){
            this.cubes = cubes;
            this.direction = direction;


            // 代表当前的模型在整个方块中的坐标
            this.$xIndex=0;

            this.$yIndex=0;

            this.$container=container;

            this.$isReachBottom=false;

            this.$xIndex=Math.round(this.$container.colCount/2-Model.DEFAULT_COL_COUNT/2);

            this.initCubes(); // 讲model挂载到cube上

            this.register();//挂载cube到container上面

            this.draw()
        }

        initCubes(){
            this.cubes.forEach(cube => {
                cube.$model=this;
            })
        }

        draw(){
            this.cubes.forEach(cube => {cube.draw()})
        }

        rotate(){
            this.direction = this.direction % 4 + 1;
            //旋转操作
            // 遍历所有cube

            let isBelowBottom=false
            this.cubes.forEach(cube=>{
                let temp=cube.$xIndex;
                cube.$xIndex=cube.$yIndex;
                cube.$yIndex=3-temp;

                if(this.$yIndex+cube.$yIndex>this.$container.rowCount-1){
                    isBelowBottom=true
                }
            })


            if(isBelowBottom){
                // 在下面,需要调整
                let maxY = Math.max(...this.cubes.map(item=>item.$yIndex));

                this.$yIndex=this.$container.rowCount-1-maxY;
            }

            this.draw()
        }


        move(xDirection,yDirection){
            this.$xIndex+=xDirection;


            // 如果超出左边界,则不动
            if(this.$xIndex<0){
                this.$xIndex=0;
            }

            let maxX=Math.max(...this.cubes.map(item=>item.$xIndex))


            //如果超出右边界,则不动
            if(this.$xIndex+maxX> this.$container.colCount-1){
                this.$xIndex=this.$container.colCount-1-maxX;
            }


            this.$yIndex+=yDirection;
            this.draw();
        }

        register(){
            this.cubes.forEach(cube=>{
                this.$container.$el.appendChild(cube.$el);
            })

        }

        isReachBottom(){
            // 遍历所有cube判断是否超出
            let result=this.cubes.some(cube=>{
                return (this.$yIndex+cube.$yIndex) >= this.$container.rowCount-1;
            })
            return result
        }
    }

    class LModel extends Model{
        constructor(container,cubeSize){
            let cubes = [];

            let direction=util.random(1,4);
            //创建L型
            // 创建指定方向的集合

            cubes.push(new Cube(cubeSize,{xIndex:0,yIndex:0}));

            cubes.push(new Cube(cubeSize,{xIndex:0,yIndex:1}));

            cubes.push(new Cube(cubeSize,{xIndex:1,yIndex:1}));

            cubes.push(new Cube(cubeSize,{xIndex:2,yIndex:1}));


            super(container,cubes,direction);
        }
    }

    function GameTetris(el, options) {

        // 如果没传el报错
        if(!el){
            throw new Error('el is required');
        }

        //如果el是string转为dom
        if(typeof el === 'string'){
            el = document.querySelector(el);
        }
        options = options || {};

        this.$el = el;
        this.$options = options;

        this.fallingSpeed = options.fallingSpeed||100;
        //方块的大小
        this.$cubeSize=this.$options.cubeSize||20;
        this.$left={}
        this.$right={}
        this.$currentModel=null;
        this.$bottomModels=[]
        this.$timer=null;
        this.$content={
            width: this.$options.width||300,
            height: this.$options.height||600,
        }
        this.$content.rowCount = Math.floor(this.$content.height/this.$cubeSize);
        this.$content.colCount = Math.floor(this.$content.width/this.$cubeSize);


        this.init();
    }


    GameTetris.prototype.init = function(){

        this.initContainer();
        this.start();
    }

    GameTetris.prototype.initContainer = function(){
        let left = document.createElement('div');
        this.$left.$el=left;
        let content = document.createElement('div');
        this.$content.$el=content;
        let right = document.createElement('div');
        this.$right.$el=right;
        let container = this.$el;
        container.appendChild(left)
        container.appendChild(content)
        container.appendChild(right)
        this.initLeft();
        this.initContent();
        this.initRight();
    }


    GameTetris.prototype.initLeft = function(){
    }

    GameTetris.prototype.initRight = function(){
    }

    GameTetris.prototype.initContent = function(){
        let contentEl = this.$content.$el;
        contentEl.id='game-panel-content'
        contentEl.style.width = this.$content.width + 'px';
        contentEl.style.height = this.$content.height + 'px';
        contentEl.style.position = 'relative';
        let lModel = this.createModel();
        this.$currentModel = lModel;
    }


    GameTetris.prototype.createModel = function(){
        return new LModel(this.$content,this.$cubeSize);
    }

    GameTetris.prototype.onReachBottom = function(){
        this.$bottomModels.push(this.$currentModel)
        this.$currentModel=this.createModel();
    }

    GameTetris.prototype.start = function(){

        clearTimeout(this.$timer);
        // 先清空,在添加
        window.removeEventListener('keydown', this.onkeydown)

        const handleTimer=()=>{
            this.moveDown();
            this.$timer=window.setTimeout(handleTimer,this.fallingSpeed)
        }

        window.setTimeout(handleTimer,this.fallingSpeed)

        window.addEventListener('keydown', this.onkeydown)
    }

    GameTetris.prototype.stop = function(){
        clearTimeout(this.$timer);
        window.removeEventListener('keydown', this.onkeydown)
    }

    GameTetris.prototype.destroy = function(){

        window.removeEventListener('keydown', this.onkeydown)
    }

    GameTetris.prototype.moveLeft = function(){
        this.move(-1,0)
    }

    GameTetris.prototype.moveRight = function(){
        this.move(1,0)
    }

    GameTetris.prototype.moveUp = function(){
        this.move(0,-1)
    }

    GameTetris.prototype.moveDown = function(){
        this.move(0,1)
    }

    /**
     * 移动
     * @param xDirection 1 向右 -1 向左 0 不移动
     * @param yDirection 1 向下 -1 向上 0 不移动
     */
    GameTetris.prototype.move = function(xDirection,yDirection){
        let currentModel = this.$currentModel;

        if(currentModel.isReachBottom()){
            this.onReachBottom();
        }else{
            currentModel.move(xDirection,yDirection);
        }



    }

    GameTetris.prototype.rotate = function(){
        let currentModel = this.$currentModel;
        currentModel.rotate();
    }
    GameTetris.prototype.onkeydown = function(event){

            switch(event.keyCode){
                case 27:
                    window.gameTetris.stop()
                    return;
                case 37:
                    window.gameTetris.moveLeft()
                    return;
                case 38:
                    window.gameTetris.rotate()
                    return;
                case 39:
                    window.gameTetris.moveRight()
                    return;
                case 40:
                    window.gameTetris.moveDown()
                    return;
            }


    }


    window.onload = function(){
        window.gameTetris = new GameTetris('#game-panel',{
            fallingSpeed:100
        });
    }

    window.onbeforeunload = function(){
        console.log("GameTetris.onbeforeunload()");
        window.gameTetris.destroy();
        window.gameTetris = null;
    }
})(window)